﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once

#include "GmStructureFamily.h"
#include "GbmpConstants.h"
#include "ProjectReferenceTypeOfReferencePlane.h"

#define MEP_TEE_TEMPLATE_NAME           L"MEPTeeComponent"
#define MEP_CROSS_TEMPLATE_NAME         L"MEPCrossComponent"
#define MEP_ELBOW_TEMPLATE_NAME         L"MEPElbowComponent"
#define MEP_TRANSITION_TEMPLATE_NAME    L"MEPTransitionComponent"

namespace gcmp
{
    class IDocument;
    class IReferencePlane;
    class IModelView;
    class UniIdentity;
}
namespace gfam
{
    class IFamilyParameterDefinition;
    class IFamilyManager;
    class IFamilyReferenceLine;
}

namespace gfam
{
    // 机电模板

    struct TeeParametersValue
    {
    public:
        TeeParametersValue()
            : shoulderLength(5)
            , length_3a(150)
            , length_3(length_3a + shoulderLength)
            , length_1a(150)
            , length_1(length_1a + shoulderLength)
        {}

    public:
        const double shoulderLength;
        const double length_3a;
        const double length_3;
        const double length_1a;
        const double length_1;
    };
    struct CrossParametersValue
    {
    public:
        CrossParametersValue()
            : shoulderLength(75)
            , length_3(225)
            , length_1(225)
        {}

    public:
        const double shoulderLength;
        const double length_3;
        const double length_1;
    };
    struct ElbowParametersValue
    {
    public:
        ElbowParametersValue()
            : radius(450)
            , angle(45.0 * gcmp::Constants::MATH_PI / 180.0)
            , length_1(radius * std::tan(angle / 2.0))
        {}
    public:
        const double radius;
        const double angle;
        const double length_1;
    };

    class GM_STRUCTURE_FAMILY_EXPORT FamMEPTemplateUtility
    {
    public:
        // 三通接头模板
        static void InitTeeFamilyDocument(gcmp::IDocument* pDoc);

        // 四通接头模板
        static void InitCrossFamilyDocument(gcmp::IDocument* pDoc);

        // 弯头模板
        static void InitElbowFamilyDocument(gcmp::IDocument* pDoc);

        // 过渡件模板
        static void InitTransitionFamilyDocument(gcmp::IDocument* pDoc);

    private:
        // 三通
        static void AddTeeLengthParameters(gfam::IFamilyManager* pFM, std::vector<gfam::IFamilyParameterDefinition*>& newParamDefs, const TeeParametersValue& paramsValue);
        static void AddTeeReferenceLineConstraint(gcmp::IDocument* pDoc,
            const std::vector<gcmp::IReferencePlane *>& newRefPlanes,
            const std::vector<gfam::IFamilyReferenceLine*>& newRefLines,
            const gcmp::Coordinate3d& workPlaneCoord);
        static void CreateTeeTemplate(gcmp::IDocument* pDoc,
            std::vector<gcmp::IReferencePlane *>& newRefPlanes,
            std::vector<gfam::IFamilyReferenceLine*>& newRefLines,
            double length_1, double length_3);
        static void CreateTeeReferencePlane(gcmp::IDocument* pDoc, std::vector<gcmp::IReferencePlane *>& newRefPlanes);
        static void CreateTeeReferenceLine(gcmp::IDocument* pDoc, std::vector<gfam::IFamilyReferenceLine*>& newRefLines, const gcmp::ElementId& workPlaneId);

        // 四通
        static void AddCrossLengthParameters(gfam::IFamilyManager* pFM, std::vector<gfam::IFamilyParameterDefinition*>& newParamDefs, const CrossParametersValue& paramsValue);
        static void AddCrossReferenceLineConstraint(gcmp::IDocument* pDoc,
            const std::vector<gfam::IFamilyReferenceLine*>& newRefLines,
            const gfam::IFamilyReferenceLine* pLine3,
            const gcmp::Coordinate3d& workPlaneCoord);
        static gcmp::IReferencePlane * CreateCrossReferencePlane(gcmp::IDocument* pDoc);

        // 弯头
        static void AddElbowLengthParameters(gfam::IFamilyManager* pFM, std::vector<gfam::IFamilyParameterDefinition*>& newParamDefs, const ElbowParametersValue& paramsValue);
        static void CreateElbowReferenceLine(gcmp::IDocument* pDoc, std::vector<gfam::IFamilyReferenceLine*>& newRefLines, const gcmp::IModelView* pModelView);

        // 过渡件
        static void CreateTransitionReferencePlane(gcmp::IDocument* pDoc, std::vector<gcmp::IReferencePlane *>& newRefPlanes);

        // 通用方法
        static IFamilyParameterDefinition* AddFamilyParameter(gfam::IFamilyManager* pFM,
            const std::wstring& strParamName,
            double dValue,
            const gcmp::UniIdentity& utId,
            bool bFormula,
            const std::wstring& formula);
        static void AddMEPThicknessParameter(gfam::IFamilyManager* pFM);
        static gcmp::IReferencePlane * GetReferencePlane(gcmp::IDocument* pDoc, gcmp::ProjectReferenceTypeOfReferencePlane refPlaneType);
    };
}
